<?php

namespace We7\Dev\DebugBar;

use DebugBar\DataCollector\ExceptionsCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\TimeDataCollector;
use DebugBar\DataCollector\PDO\PDOCollector;
use DebugBar\DebugBar;
use DebugBar\Storage\FileStorage;
use We7\Dev\Controller\AssetsController;
use We7\Dev\Controller\OpenHandlerController;
use We7\Dev\DebugBar\Laravel\QueryCollector;
use We7\Dev\DebugBar\Laravel\QueryFormatter;
use We7\Dev\DebugBar\W7\W7PDOCollector;


class We7DebugBar extends DebugBar {

	private static $instance = null;
	protected $jsRenderer = null;
	private $timer = null;
	private $storage_path = null;

	private function __construct($storage_path) {
		$this->storage_path = $storage_path;
		$this->timer = new TimeDataCollector();
		$this->addCollector(new PhpInfoCollector());
		$this->addCollector(new MessagesCollector());
		$this->addCollector(new RequestDataCollector());
		$this->addCollector($this->timer);
		$this->addCollector(new MemoryCollector());
		$this->addCollector(new ExceptionsCollector());
		if (function_exists('pdo')) {
			$this->addCollector(new W7PDOCollector(\pdo()->getPDO()));
		}
		//        dd(pdo()->getPDO());
//		$this->addCollector(new PDOCollector(\pdo()->getPDO()));
//		$this->addCollector(new CacheDataCollector());
		$this->addCollector(new TemplateDataCollector());
		$this->setStorage(new FileStorage($storage_path));
		$this->registerLaravelDB();
		set_exception_handler(function ($ex){
			$this->exceptions->addException($ex);
		});
	}

	public function getStoragePath() {
		return $this->storage_path;
	}

	/**
	 * @param null $storage_path
	 * @return self
	 */
	public static function instance($storage_path = null) {
		if (is_null(static::$instance)) {
			static::$instance = new We7DebugBar($storage_path);
		}
		return static::$instance;
	}



	public function registerLaravelDB() {

		$queryCollector = new QueryCollector($this->timer);
		$queryCollector->setRenderSqlWithParams(true);
		$queryCollector->setDataFormatter(new QueryFormatter());
		$queryCollector->setShowHints(true);
		$queryCollector->setFindSource(true, array());
		if (class_exists('\Illuminate\Database\Capsule\Manager')) {
			\Illuminate\Database\Capsule\Manager::listen(
				function ($query, $bindings = null, $time = null, $connectionName = null) use ($queryCollector) {
					// Laravel 5.2 changed the way some core events worked. We must account for
					// the first argument being an "event object", where arguments are passed
					// via object properties, instead of individual arguments.

					if ( $query instanceof \Illuminate\Database\Events\QueryExecuted ) {
						$bindings = $query->bindings;
						$time = $query->time;
						$connection = $query->connection;

						$query = $query->sql;
					} else {
						$connection = \Illuminate\Database\Capsule\Manager::connection($connectionName);
					}

					$queryCollector->addQuery((string) $query, $bindings, $time, $connection);
				}
			);
		}
		$this->addCollector($queryCollector);
	}

	private function check() {
		if ($_SERVER['PATH_INFO']) {
			$path = $_SERVER['PATH_INFO'];

			if (stripos('/__debugbar/css', $path) === 0) {
				ob_clean();
				$controller = new AssetsController();
				$controller->css();
				exit;
			}

			if (stripos('/__debugbar/js', $path) === 0) {
				ob_clean();
				$controller = new AssetsController();
				$controller->js();
				exit;
			}

			if (stripos('/__debugbar/handler', $path) === 0) {
				ob_clean();
				$controller = new OpenHandlerController();
				$controller->handle();
				exit;
			}
		}
	}


	public function showOnShutdown() {
		$this->check();
		$renderer = $this->getJavascriptRenderer();
		$renderer->setBindAjaxHandlerToXHR(true);
		$siteurl  = '//'.$_SERVER['HTTP_HOST'].'/'.htmlspecialchars($_SERVER['SCRIPT_NAME']);
		$renderer->setOpenHandlerUrl($siteurl.'/__debugbar/handler');
		if ($this->isAjax()) {
			$this->sendDataInHeaders(true);
		}else {
			$renderer->renderOnShutdownWithHead();
		}

	}

	/**
	 * Returns a JavascriptRenderer for this instance
	 * @param string $baseUrl
	 * @param string $basePath
	 * @return JavascriptRenderer
	 */
	public function getJavascriptRenderer($baseUrl = null, $basePath = null)
	{
		if ($this->jsRenderer === null) {
			$this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath);
		}
		return $this->jsRenderer;
	}

	public function isAjax() {
		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
	}

	public function setOpenHandlerUrl($url) {
		$this->getJavascriptRenderer()->setOpenHandlerUrl($url);
	}

	private static function injectHtml($html, $code, $before) {
		$pos = strripos($html, $before);
		if ($pos === false) {
			return $html.$code;
		}

		return substr($html, 0, $pos).$code.substr($html, $pos);
	}
}
